/*
* "doctothumb" program converts the page(s) of a document into jpeg image files
* 
* Copyright (C) 2013 Alin Dumitrescu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.

* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
* Distributed under the GNU GPL v2. For full terms see the file Copying or
* License URL at: http://www.gnu.org/licenses/gpl.html GPL version 2
*/

#include <windows.h>
#include "../xpdf-3.03/splash/SplashTypes.h"
#include "../xpdf-3.03/xpdf/PDFDoc.h"
#include "../xpdf-3.03/xpdf/XRef.h"
#include "../xpdf-3.03/xpdf/SplashOutputDev.h"
#include "../FreeImage/Dist/FreeImage.h"

typedef struct
{
    int Resolution,                                                   //resolution in DPI
        Quality;                                                      //JPEG quality (100=max, 1=min)
}
DOC_Context,*PDOC_Context;

typedef struct IMG_Context: DOC_Context
{
    int BPP;                                                          //bits per pixel (BW = 1, GRAY = 8, RGB = 24)
}
*PIMG_Context;

typedef struct PDF_Context: DOC_Context
{
    SplashColorMode cm;                                               //the color mode (BW,GRAY,RGB,BGR)
    SplashColor* pSC;                                                 //the background color
}
*PPDF_Context;

struct MTSharedDoc;                                                   //definition

typedef struct
{
    PDOC_Context pContext;                                            //pointer to the GRBJ
    int Pages;                                                        //the requested page or pages (1..n, or 0 for all)
    char InFilename[MAX_PATH];                                        //the input document file
    char OutFolder[MAX_PATH];                                         //the output folder (without the trailing backslash "\")
    MTSharedDoc**Docs;                                                //array of documents
}
CommandRender, *PCommandRender;

typedef struct CommandExecute: CommandRender
{
    long Threads;                                                     //holds the running thread count
    char* Files;                                                      //holds the start of the output filenames buffer
    long OutputRealSize;                                              //holds the needed output buffer size
}
*PCommandExecute;

typedef struct                                                        //this structure is passed to rendering thread
{
    DWORD* OwnedPtr;                                                  //the ThreadId pointer
    PDFDoc* Doc;                                                      //the PDFDoc object
    int Page;                                                         //the requested page to render
    PCommandExecute CmdExec;                                          //the main render task
}
PDFRenderContext,*PPDFRenderContext;

extern FreeImageIO imgio;                                             //io operations for FreeImage

typedef enum IMGType {undefined,single,multi};                        //document type as multipage or single page

typedef struct IMGDoc
{
private:
    char* Filename;                                                   //the original filename
    IMGType type;                                                     //document type
    FILE* Hnd;                                                        //the handle (classic filestream)
    void* Img;                                                        //the FreeImage object
    FIBITMAP* lockpage;                                               //in multipage documents, this holds the page object to render
    FREE_IMAGE_FORMAT fmt;                                            //file type defined as FreeImage type
protected:
    int Count;                                                        //holds the page count of a document
    static void IMGUndefine(IMGDoc* Source);
    IMGDoc(char* Filename,IMGType type,FREE_IMAGE_FORMAT fmt,int Pages);
public:
    IMGDoc(char* Filename);
    ~IMGDoc();
    IMGDoc* Clone(IMGDoc* Source);
    FIBITMAP* GetPage(int Number);                                    //return either a page
    void ReleasePage();                                               //release the last locked page
    int GetCount();
    IMGType GetType();                                                //get the type of the document (undefined,single,multi)
} *PIMGDoc;

typedef struct                                                        //this structure is passed to rendering thread
{
    DWORD* OwnedPtr;                                                  //the ThreadId pointer
    IMGDoc* Img;                                                      //the image document object
    int Page;                                                         //the requested page to render
    PCommandExecute CmdExec;                                          //the main render task
}
IMGRenderContext,*PIMGRenderContext;

typedef struct
{
    PDOC_Context pContext;                                            //pointer to the GRBJ
    int Pages;                                                        //document page count or, if less than 1, error (in file Detail see Enclosure:Error codes)
    char OutFilenames[1];                                             //output filenames contains at least the NULL character
}
ResultRender,*PResultRender;

typedef enum DocType{dtpdf,dtimg};                                    //document type as PDF or IMG

typedef struct MTSharedDoc
{
private:
    DocType type;
    void* Obj;
public:
    DWORD Owned;
    MTSharedDoc(PDFDoc* doc) : Obj((void*)doc) , type(dtpdf) {};
    MTSharedDoc(IMGDoc* doc) : Obj((void*)doc) , type(dtimg) {};
    ~MTSharedDoc()
    {
        switch(type)
        {
        case dtpdf:
            delete ((PDFDoc*)Obj);
            break;
        case dtimg:
            delete ((IMGDoc*)Obj);
            break;
        default:;
        }
        Obj = NULL;
    };
    PDFDoc* PDF()
    {
        return (type == dtpdf) ? ((PDFDoc*)Obj) : NULL;
    };
    IMGDoc* IMG()
    {
        return (type == dtimg) ? ((IMGDoc*)Obj) : NULL;
    };
}*PSharedDoc;

extern void CreateUniqueFile(                                         //self explanatory 
  unsigned char charlen,                                              //how many random characters filename must have
  char* Path,                                                         //destination folder 
  char* Filename);                                                    //generated filename (output)

extern HWND hWnd;                                                     //window handle
extern HWND hWndParent;                                               //parent hWnd
extern char szTitle[];                                                //the title bar text
extern char szWindowClass[];                                          //the main window class name
extern int volatile MaxThreads;                                       //Maximum worker threads

extern SplashColor SCMMono;                                           //backgound color of
extern SplashColor SCMColor;                                          //the raster surface

extern ATOM                app_register(HINSTANCE hInstance);         //declare the application class register function
extern BOOL                InitInstance(HINSTANCE, int);              //declare the application instance initialization function
extern LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);       //declare the most important callback in a windowed application
extern void ProcessLoop();                                            //declare application's main loop

//Bof PDF Rendering functions
extern void PDFProcessStartRender(PCommandRender pCR);                //start to Render a PDF document
extern void __stdcall PDFThreadedStartRender(PCommandExecute pCE);    //thread function for threaded task processing
extern void PDFRenderProcess(PCommandExecute pCE);                    //threaded task processing
extern void __stdcall PDFRenderPage(PPDFRenderContext pRC);           //thread function for threaded rendering
extern void PDFProcessPage(PPDFRenderContext pRC);                    //threaded rendering
extern void PDFProcessSavePage(int bpp, SplashOutputDev* splashOut,
                char* OutFilename, int Quality);                      //save the output to file 
extern void PDFAddFileToList(PCommandExecute pCE,
                char* Filename,int Page);                             //add filename to the output filename buffer
//Eof PDF Rendering functions

//Bof IMG Rendering functions
extern void IMGProcessStartRender(PCommandRender pCR);                //start to Render a image document
extern void __stdcall IMGThreadedStartRender(PCommandExecute pCR);    //thread function for threaded task processing
extern void IMGRenderProcess(PCommandExecute pCE);                    //threaded task processing
extern void __stdcall IMGRenderPage(PIMGRenderContext pRC);           //thread function for threaded rendering
extern void IMGProcessPage(PIMGRenderContext pRC);                    //threaded rendering
extern void IMGAddFileToList(PCommandExecute pCE,
                char* Filename,int Page);                             //add filename to the output filename buffer
//Eof IMG Rendering functions

//Common functions
extern void PostResult( int AErrorCode, PCommandRender pCR,
                char* Files = NULL);                                  //post (actually send) a message to the parent application

//Messages
#define WM_MSG_APP                     WM_USER                        //the base msg

//command set for WM_MSG_APP
#define WP_DESTROY_CTX                 123456781                      //destroy the no longer needed GRBJ
#define WP_CREATE_PDF_CTX              123456782                      //create a new "Context" into the app, returns the GRBJ pointer
#define WP_CREATE_IMG_CTX              123456783                      //create a new "Context" into the app, returns the GRBJ pointer

//command set for WM_COPYDATA 
#define WP_RENDER_DONE                 223456781                      //task job is over and the data is transferred to parent
#define WP_START_PDF_RENDER            223456782                      //create a new task for PDF rendering
#define WP_START_IMG_RENDER            223456783                      //create a new task for IMG rendering

//command set for WM_MSGPDF_APP CALLBACK
#define WP_APPLICATION_ACK             923456781                      //notification to the parent process for loading/initializing complete
